home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tree / tex.c < prev    next >
C/C++ Source or Header  |  1993-09-01  |  18KB  |  671 lines

  1.  
  2.  
  3. /*
  4.  * With the -u option, TeX \special commands are used to include
  5.  * PostScript commands into the PS file created by the PS driver
  6.  * (dvi2ps, psdvi, dvips, dvitops, or whatever).  The driver should
  7.  * not attempt repositioning or anything -- just copy to its output.
  8.  * Some drivers may not be willing to do this, and others may need
  9.  * the \special to begin with a certain keyword before they will do it.
  10.  * Here is a list of those keywords I know about:
  11.  *    "ps-string "
  12.  *    "ps-string="
  13.  *    "ps::"
  14.  *    "pstext="
  15.  * The following define is for this keyword; it might have to be set
  16.  * to one of the above.  (My version of dvi2ps does not require a
  17.  * keyword.)
  18.  */
  19. #ifndef SKEY
  20. #define SKEY "ps::"
  21. #endif
  22.  
  23. /*
  24.  * Dimensions are in terms of em and ex (of the current font), with
  25.  * basic values assuming cmr 10, which has 1em = 10pt, 1ex = 4.31pt.
  26.  *
  27.  * Each character or space is reckoned to be 1/2 em, which is the
  28.  * width of a digit in the cmr fonts.  However, each `col' unit in
  29.  * the tree is a half-space wide -- 1/4 em, that is.
  30.  *
  31.  * The normal width of rules is .4pt, which becomes .04em.
  32.  * The height of lines is that of a TeX \strut: 8.5pt above the
  33.  * baseline and 3.5pt below, and in ex units:
  34.  *    8.5pt/4.31=1.972ex
  35.  *    3.5pt/4.31=0.81206ex
  36.  * The horizontal bars made of "underlines" have vertical dimension
  37.  * starting 3.5pt below the baseline and going up .4pt to:
  38.  *    3.1pt/4.31=0.71925ex
  39.  * The ones made of "overlines" go to 8.5pt and start .4pt lower:
  40.  *    8.1pt/4.31=1.87935ex
  41.  * Rule width is .4pt/4.31 = .09280742ex.
  42.  */
  43.  
  44. float   hskip = 0;        /* amount to hskip before next box or bar */
  45.  
  46. dohskip () {
  47.     /* must emit this even when hskip is 0 to get out of
  48.      * vertical mode before an \hbox
  49.      */
  50.     printf ("\\hskip %.2fem", hskip);
  51.     hskip = 0;
  52. }
  53.  
  54. /* record keeping for lines connecting discontinuous constituents */
  55. int m_ulabel[11];
  56. int d_ulabel[11];
  57.  
  58. /*
  59.  * Keep track of the attributes from the \M and \D label
  60.  * commands.  For the first of a matching pair, save our treeid
  61.  * in the ulabel array and issue PS commands to define the current
  62.  * (x,y) coordinates with names corresponding to the treeid.  For
  63.  * the second of a matching pair, issue PS commands to draw a
  64.  * line back to the previous location.
  65.  */
  66. setiattrib(node, is_daughter)
  67. TREE node;
  68. int *is_daughter;
  69. {
  70.     int type = node->type;
  71.     int iattrib = 0;
  72.  
  73.     if (type == VBAR && (iattrib = has(node,'D')) ) {
  74.     /* this is a daughter label */
  75.     *is_daughter = TRUE;
  76.     /* ... unless we're in an inverted tree */
  77.     /*if (node->mother && node->mother->type == OBAR)*/
  78.     if (has(node,'U') == 'i')
  79.         *is_daughter = FALSE;
  80.     if (iattrib == '+') iattrib = 10;
  81.     else iattrib -= '0';
  82.     d_ulabel[iattrib] = node->treeid;
  83.     /* if known already, get old treeid in iattrib, otherwise
  84.      * note with "-1" that current location must be defined
  85.      */
  86.     if (m_ulabel[iattrib]) iattrib = m_ulabel[iattrib];
  87.     else iattrib = -1;
  88.     }
  89.     else if ((type==HBAR || type==VBAR || type==OBAR)
  90.                 && (iattrib = has(node,'M'))) {
  91.     /* this is a mother label */
  92.     *is_daughter = FALSE;
  93.     /* ... unless we're an OBAR: */
  94.     if (type == OBAR) *is_daughter = TRUE;
  95.     if (type == VBAR && has(node,'U') == 'i') *is_daughter = TRUE;
  96.     if (iattrib == '+') iattrib = 10;
  97.     else iattrib -= '0';
  98.     m_ulabel[iattrib] = node->treeid;
  99.     if (d_ulabel[iattrib]) iattrib = d_ulabel[iattrib];
  100.     else iattrib = -1;
  101.     }
  102.  
  103.     if (debug_opt) printf("%% note iattrib %d\n", iattrib);
  104.  
  105.     return(iattrib);
  106. }
  107.  
  108.  
  109.  
  110. /* TeX height and depth to be used in current line for strut, etc. */
  111. float h, d;
  112. /* used only in following routine, except also set in print_tex_tree */
  113. int curr_row = -1;
  114. /* look at entire row to see what the smallest height and depth we can
  115.  * get away with are
  116.  */
  117. static
  118.         set_hd (node)
  119.         TREE node;
  120. {   int     row_type = 0;
  121.     int     top_row = node->row;
  122.  
  123.     if (top_row == curr_row) return;
  124.     curr_row = top_row;
  125.     while (node && (node->row == top_row)) {
  126.     row_type |= node->type;
  127.     node = node->right;
  128.     }
  129.     if (row_type & NODENAME) {
  130.     if (debug_opt) printf("%% Next row needs a full size strut.\n");
  131.     h = 1.972;
  132.     d = .812;
  133.     }
  134.     else {
  135.     /* Make rows without text for node names about 2/3 of normal size.
  136.      */
  137.     if (debug_opt) printf("%% Setting height + depth to 2 ex's.\n");
  138.     h = 1.5;
  139.     d = .5;
  140.     }
  141. }
  142.  
  143.  
  144. /* Generate PS code for Bezier curve connecting discontinuous
  145.  * constituents (needs work).  This has to be independent of scale
  146.  * or translation of coordinate system, since the PS driver may
  147.  * have changed these.
  148.  */
  149. curvegen(sf, is_daughter)
  150. char *sf;
  151. int is_daughter;
  152. {
  153.     if (is_daughter) printf("\\lower%1.3fex",d);
  154.     else printf("\\raise%1.3fex",h);
  155.  
  156.     printf("\\hbox{\\special{%scurrentpoint ",SKEY);
  157.  
  158.   /* Daughter is at, say, (DX,DY) and mother at (MX,MY);
  159.    * if we're now at the daughter, we need to calculate two
  160.    * inflexion points, somehow.  (Even though the PS variable
  161.    * is called "mom", if we're at a mother node, it's actually
  162.    * a daughter.)
  163.    */
  164.   if (is_daughter) {
  165.     printf("currentpoint pop mom%sy ",sf);    /* (DX,MY) */
  166.     printf("mom%sx currentpoint exch pop ",sf);    /* (MX, (DY+MY)/2 ) */
  167.     printf("mom%sy add 2 div ",sf);
  168.   }
  169.   else {
  170.   /* We're at the mother, and the first inflexion point has to bend
  171.    * us down, then the second has be up above the daughter so we hit
  172.    * it going more or less downward.
  173.    */
  174. /* cpx */
  175.     printf("currentpoint pop ");
  176. /* cpy 2 mul dy sub */
  177.     printf("currentpoint exch pop 2 mul mom%sy sub ",sf);
  178.                     /* (MX, MY*2 - DY)  */
  179. /* dx */
  180.     printf("mom%sx ",sf);
  181. /* dy 2 mul cpy sub */
  182.     printf("mom%sy 2 mul currentpoint exch pop sub ",sf);
  183.                     /* (DX, DY*2 - MY)   */
  184. /* dx dy */
  185.   }
  186.     /* and wind up at (DX,DY) or (MX,MY)  */
  187.     printf("mom%sx mom%sy curveto stroke ",sf,sf);
  188.  
  189.     printf("moveto}}%%\n");
  190. }
  191.  
  192. char    m[4], n[4];
  193. /* m and n are suffixes for PS identifiers initialized here for
  194.  * later use.  m is for local lines; n is for discontinuous
  195.  * constituent lines requested through labels
  196.  */
  197. setsuffix(s, id)
  198. char *s;
  199. int id;
  200. {
  201.     s[0] = 'a'; s[1] = 'a'; s[2] = 'a'; s[3] = '\0';
  202.     s[0] += id / (26*26);
  203.     s[1] += (id / 26) % 26;
  204.     s[2] += id % 26;
  205. }
  206.  
  207. char *whichbar[] = {
  208.     "",
  209.     "\\big\\Vert",
  210.     "\\big\\downarrow",
  211.     "\\big\\Downarrow",
  212.     "\\big\\uparrow",
  213.     "\\big\\Uparrow",
  214.     "\\big\\updownarrow",
  215.     "\\diamondsuit",
  216.     "\\triangle",
  217.     ""
  218. };
  219. char *whichobar[] = {
  220.     "",
  221.     "\\big\\Vert",
  222.     "\\big\\uparrow",
  223.     "\\big\\Uparrow",
  224.     "\\big\\downarrow",
  225.     "\\big\\Downarrow",
  226.     "\\big\\updownarrow",
  227.     "\\diamondsuit",
  228.     "\\nabla",
  229.     ""
  230. };
  231.  
  232. int greyness;
  233.  
  234.     /* The vertical bars start horizontally half way through a
  235.      * character space and go .4pt further to the right.  For the
  236.      * -u option, issue PS to draw a line to the previously defined
  237.      * position under the node name above.  (For upside down trees,
  238.      * the position over the node name below is unfortunately not yet
  239.      * defined -- haven't figured out what to do about that -- not
  240.      * sure I care enough.)
  241.      */
  242. texvbar(node, iattrib, r, is_daughter)
  243. TREE node;
  244. int iattrib, is_daughter;
  245. float r;
  246. {    TREE mom = node->mother;
  247.     int do_a_line = FALSE,
  248.         do_a_bar = FALSE,
  249.         do_a_tbar = FALSE,
  250.         do_nothing = FALSE,
  251.         def_a_sister = FALSE,
  252.         def_an_osister = FALSE,
  253.         def_a_mother = FALSE,
  254.         do_a_triangle = FALSE,
  255.         do_a_box = FALSE,
  256.         do_an_obox = FALSE;
  257.  
  258.     do_a_line = (utex_opt && mom && mom->type == HBAR);
  259.     if (mom && mom->row > node->row) do_a_line = FALSE;
  260.  
  261.     def_an_osister = (!has(node,'O') && utex_opt
  262.                 && mom && mom->type == OBAR);
  263.     if (def_an_osister) {
  264.         def_a_sister = TRUE;
  265.         if (has(node,'S') == 'f' || has(node,'S') == 'o')
  266.             mom->left = node;
  267.         if (has(node,'S') == 'o') def_a_mother = TRUE;
  268.     }
  269.  
  270.     if (do_a_line && has(node,'T') && !has(node,'B')) {
  271.         if (has(node,'S') == 'f' || has(node,'S') == 'o')
  272.             def_a_sister = TRUE;
  273.         if (has(node,'S') == 'o' || has(node,'S') == 'l')
  274.             do_a_triangle = TRUE;
  275.         if (!do_a_triangle && !def_a_sister) do_nothing = TRUE;
  276.     }
  277.  
  278.     if (has(node,'O') || has(node,'P')) do_nothing = TRUE;
  279.     if (iattrib && utex_opt) do_nothing = FALSE;
  280.     if (utex_opt && iattrib == -1) def_a_mother = TRUE;
  281.     do_a_bar = (!do_a_line && !do_nothing && !def_an_osister);
  282.     if (has(node,'B')) do_a_bar = TRUE;
  283.     if (do_a_bar && has(node,'T')) {
  284.         if (has(node,'S') == 'f' || has(node,'S') == 'o') {
  285.         if (mom && mom->type == OBAR) do_an_obox = TRUE;
  286.         /*else if (mom && node == mom->daughter) do_a_box = TRUE;*/
  287.         else /*if (mom && node == mom->daughter)*/ do_a_box = TRUE;
  288.         do_nothing = TRUE;
  289.         }
  290.         else do_nothing = TRUE;
  291.     }
  292.     if (has(node,'O') || has(node,'P')) do_a_bar = FALSE;
  293.     if (do_a_bar && (!utex_opt || has(node,'B')) && whichbar[b][0]) {
  294.         do_a_tbar = TRUE;
  295.         do_a_bar = FALSE;
  296.     }
  297.  
  298.     hskip += .25;
  299.  
  300.     if (do_a_box || do_an_obox) {
  301.     TREE first = node, last;
  302.     int len;
  303.     while (node->sister
  304.           && node->mother == node->sister->mother
  305.           && has(node,'S') != 'l'
  306.           && has(node,'S') != 'o'
  307.           && node->sister->type == VBAR) {
  308.         node->mother = NULL;
  309.         node = node->sister;
  310.     }
  311.     last = node;
  312.     last->mother = NULL;
  313.     if (first != last) {
  314.         len = last->col + last->l - first->col;
  315.         r = len;
  316.         r /= COLMUL;
  317.     }
  318.     dohskip();
  319.     printf ("\\vrule width.04em");
  320.     hskip -= .04;
  321.     if (greyness) {
  322.         printf ("\\xleaders\\hbox to .%dem{\\hss$\\",
  323.         greyness);
  324.         if (do_a_box) printf("Down");
  325.         else printf("Up");
  326.         printf ("arrow$\\hss}\\hskip%.2fem\n",
  327.         r/2 - .50 - .04);
  328.     }
  329.     else {
  330.     if (do_a_box)
  331.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  332.         r/2 - .50 - .04, .09281 - d, d);
  333.     else
  334.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  335.         r/2 - .50 - .04, h, .09281 - h);
  336.     }
  337.     if (first != last) hskip -= (r/2 - .50);
  338.     printf ("\\vrule width.04em");
  339.     }
  340.  
  341.  
  342.  
  343.     if (do_nothing) {
  344.         hskip += .25;
  345.         return;
  346.     }
  347.     dohskip();
  348.     if (do_a_bar) {
  349.         printf ("\\vrule width.04em%%\n");
  350.         hskip -= .04;
  351.     }
  352.     if (do_a_line) {
  353.         setsuffix(m, mom->treeid);
  354.         printf("\\lower%1.3fex\\hbox{\\special{%scurrentpoint",d,SKEY);
  355.     }
  356.     if (def_an_osister) {
  357.         setsuffix(m, node->treeid);
  358.         printf("\\raise%1.3fex\\hbox{\\special{%scurrentpoint",h,SKEY);
  359.     }
  360.     if (def_a_sister)
  361.         printf(" /sis%sy exch def /sis%sx exch def}}%%\n",m,m);
  362.     if (do_a_triangle) {
  363.         if (def_a_sister) {
  364.             hskip += r/2 - .75;
  365.             dohskip();
  366.             hskip += .25;
  367.             printf("\\lower%1.3fex\\hbox{",d);
  368.             printf("\\special{%scurrentpoint",SKEY);
  369.         }
  370.         printf(" sis%sx sis%sy lineto mom%sx mom%sy lineto",m,m,m,m);
  371.         printf(" closepath");
  372.         if (greyness)
  373.             printf(" .%d setgray fill 0 setgray", greyness);
  374.         else printf(" stroke");
  375.     }
  376.     if (do_a_line && !do_a_tbar && !def_a_sister && !do_a_triangle
  377.         && !do_a_bar && !has(node,'O') && !has(node,'P'))
  378.         printf(" mom%sx mom%sy lineto stroke",m,m);
  379.  
  380.     if (do_a_line && (do_a_triangle || !def_a_sister)) {
  381.         printf(" moveto}}%%\n");
  382.     }
  383.     if (def_a_mother) {
  384.         if (def_an_osister) {
  385.             hskip += r/2 - .75;
  386.             dohskip();
  387.             hskip += .25;
  388.             is_daughter = FALSE;
  389.         }
  390.         setsuffix(n, node->treeid);
  391.         if (is_daughter) printf("\\lower%1.3fex",d);
  392.         else printf("\\raise%1.3fex",h);
  393.         printf("\\hbox{\\special{%s currentpoint",SKEY);
  394.         printf(" /mom%sy exch def /mom%sx exch def}}%%\n",n,n);
  395.     }
  396.     if (utex_opt && iattrib > 0) {
  397.         setsuffix(n, iattrib);
  398.         curvegen(n, is_daughter);
  399.     }
  400.     if (do_a_tbar) {
  401.         hskip -= .25 - .04;
  402.         dohskip();
  403.         printf("\\hbox to 0.5em{\\hss$%s$\\hss}%%\n",
  404.             (has(node,'U') == 'i')? whichobar[b] : whichbar[b]);
  405.         hskip -= .25 + .04;
  406.     }
  407.  
  408.     hskip += .25;
  409. }
  410.  
  411.  
  412.  
  413.     /* Horizontal bars also start half way through a space.
  414.      * They have a vertical bar in the center and extend .4pt
  415.      * further than half way through a character space at the
  416.      * end to cap the vertical bar that will come below.
  417.      * For the -u option, instead of rules, generate PS code
  418.      * to remember the coordinates under the node name above, so
  419.      * later can draw line from daughters back to here.
  420.      */
  421. texhbar(node, iattrib, r, rm, is_daughter)
  422. TREE node;
  423. int iattrib, is_daughter;
  424. float r, rm;
  425. {    TREE mom = node->mother;
  426.  
  427.     if (utex_opt && !has(node,'B')) {
  428. /* REVISE HERE */
  429. /* rm/2 + (r - rm)/2 = rm/2 + r/2 - rm/2 = r/2 */
  430.  
  431.     hskip += rm/2 + .25;
  432.     dohskip ();
  433.     if (debug_opt) printf("%% Here is mom [%d]\n", node->treeid);
  434.     printf("\\raise%1.3fex\\hbox{\\special{%scurrentpoint",h,SKEY);
  435.         setsuffix(m, node->treeid);
  436.     printf(" /mom%sy exch def /mom%sx exch def}}%%\n",m,m);
  437.     if (iattrib > 0) {
  438.         setsuffix(n, iattrib);
  439.         curvegen(n, is_daughter);
  440.     }
  441.     hskip += (r - rm)/2 - .25;
  442.     } else {
  443.     float w;
  444.     hskip += .25;
  445.     dohskip ();
  446.     if (b == 9 && r >= 6)
  447.         printf("\\hbox to %.2fem{\\downbracefill}%%\n",
  448.             r/2 - .50 + .04);
  449.     else if (!node->mother)
  450.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  451.             r/2 - .50 + .04, .09281 - d, d);
  452.     else {
  453.         if ((w = rm/2) > .01)
  454.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  455.             w, .09281 - d, d);
  456.         printf ("\\vrule width.04em");
  457.         if ((w = r/2 - w - .50) > .01)
  458.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  459.             w, .09281 - d, d);
  460.     }
  461.     hskip += .25 -.04;
  462.     }
  463. }
  464.  
  465.  
  466.  
  467. texobar(node, iattrib, r, rm, is_daughter)
  468. TREE node;
  469. int iattrib, is_daughter;
  470. float r, rm;
  471. {
  472.     /* "left" is actually a pointer up to first daughter */
  473.     if (utex_opt && !has(node,'B') && node->left && node->left->mother == node
  474.                     && node->left->type == VBAR) {
  475.     TREE sis = node->left;
  476.     hskip += rm/2 + .25;
  477.     dohskip ();
  478.     if (debug_opt) printf("%% Here is bottom pt [%d]\n", node->treeid);
  479.     printf("\\lower%1.3fex\\hbox{\\special{%scurrentpoint",d,SKEY);
  480.  
  481.     if (iattrib == -1) {
  482.         setsuffix(n, node->treeid);
  483.         printf(" currentpoint /mom%sy exch def /mom%sx exch def",n,n);
  484.     }
  485.  
  486.     while (sis && sis->mother == node) {
  487.         if (has(sis,'O') || has(sis,'P')) {
  488.         sis = sis->sister;
  489.         continue;
  490.         }
  491.             setsuffix(m, sis->treeid);
  492.         if (has(node,'T')) {
  493.         if (has(node,'S') == 'f'
  494.             || has(node,'S') == 'l'
  495.             || has(node,'S') == 'o')
  496.             printf(" sis%sx sis%sy lineto",m,m);
  497.         }
  498.         else printf(" currentpoint sis%sx sis%sy lineto moveto",m,m);
  499.         if (has(node,'T') && has(node,'S') == 'o')
  500.             printf(" mom%sx mom%sy lineto",m,m);
  501.         sis = sis->sister;
  502.     }
  503.     if (has(node,'T')) {
  504.         printf(" closepath");
  505.         if (greyness)
  506.             printf(" .%d setgray fill 0 setgray", greyness);
  507.         else printf(" stroke");
  508.     }
  509.     else printf(" stroke");
  510.     printf(" moveto}}%%\n");
  511.     if (iattrib > 0) {
  512.         setsuffix(n, iattrib);
  513.         curvegen(n, is_daughter);
  514.     }
  515.     hskip += (r - rm)/2 - .25;
  516.  
  517.     }
  518.     else {
  519.     float w;
  520.     hskip += .25;
  521.     dohskip ();
  522.     if (b == 9 && r >= 6)
  523.         printf("\\hbox to %.2fem{\\upbracefill}%%\n",
  524.             r/2 - .50 + .04);
  525.     else if (node->mother && node->right) {
  526.         if ((w = rm/2) > .01)
  527.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  528.             w, h, .09281 - h);
  529.         printf ("\\vrule width.04em");
  530.         if ((w = r/2 - w - .50) > .01)
  531.         printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  532.             w, h, .09281 - h);
  533.     }
  534.     else printf ("\\vrule width%.2fem height%1.3fex depth%1.3fex%%\n",
  535.             r/2 - .50 + .04, h, .09281 - h);
  536.     hskip += .25 - .04;
  537.     }
  538. }
  539.  
  540. texnodename(node, r)
  541. TREE node;
  542. float r;
  543. {
  544.     if (has(node,'P')) hskip += r/2;
  545.     else {
  546.         dohskip ();
  547.         if (has(node,'R'))
  548.             printf ("\\hbox to %.2fem{\\hss{%s}}%%\n",
  549.                 r/2, node->n);
  550.         else printf ("\\hbox to %.2fem{\\hss{%s}\\hss}%%\n",
  551.                 r/2, node->n);
  552.     }
  553. }
  554.  
  555. /* emit TeX code for a bar or a box containing a node name */
  556. boxitup (node)
  557. TREE node;
  558. {
  559.     float   r = node->l, rm;
  560.     int     iattrib = 0;
  561.     int     is_daughter;
  562.     int     i;
  563.     TREE    mom = node->mother;
  564.  
  565.     if (b = has(node,'B')) {
  566.         if (b == '+') b = 9;
  567.         else if (isdigit(b)) b -= '0';
  568.         else b = 0;
  569.         greyness = b;
  570.     }
  571.     else {
  572.         for (b = black_opt; b > 10; b /= 10) ;
  573.         for (greyness = black_opt; greyness >= 100; greyness /= 10);
  574.     }
  575.     if (greyness > 9) greyness = 100 - greyness;
  576.     else if (greyness) greyness = 10 - greyness;
  577.  
  578.     if (mom && node != mom->daughter && node->sister) mom = NULL;
  579.  
  580.     /* set height and depth for raising and lowering and for strut
  581.      * at end of line
  582.      */
  583.     set_hd(node);
  584.  
  585.     iattrib = setiattrib(node, &is_daughter);
  586.  
  587.     /* halve width to compensate for doubling col values */
  588.     r /= COLMUL;
  589.     i = node->mid;
  590.     if (COLMUL > 2) i /= (COLMUL/2);
  591.     rm = i;
  592.     if (COLMUL > 1) rm /= 2;
  593.  
  594.   /* now generate TeX code for VBARs, HBARs, and NODENAMEs */
  595.     switch(node->type) {
  596.         case VBAR:    texvbar(node, iattrib, r, is_daughter);
  597.                 break;
  598.         case HBAR:    texhbar(node, iattrib, r, rm, is_daughter);
  599.                 break;
  600.         case OBAR:    texobar(node, iattrib, r, rm, is_daughter);
  601.                 break;
  602.         case NODENAME:    texnodename(node, r);
  603.                 break;
  604.     }
  605. }
  606.  
  607.  
  608. /* Like preceding routine tex(), except collect spaces and
  609.  * emit globs of TeX \hskip, \hbox, and \vrule commands (for
  610.  * respectively space, node names, and tree lines).
  611.  */
  612. tex(tree)
  613. TREE tree;
  614. {
  615.     int     row = tree->row,
  616.         col = 0,
  617.         i;
  618.  
  619.     hskip = (float) indent / 2;
  620.  
  621.     /* mark all labels as undefined */
  622.     for (i = 0; i < 11; i++) {
  623.     m_ulabel[i] = 0;
  624.     d_ulabel[i] = 0;
  625.     }
  626.      /* make sure set_hd looks at first row */
  627.     curr_row = -1;
  628.  
  629.     /* Each line of the tree will be a paragraph, so prevent white space
  630.      * breaking up segments of vertical rules; put a strut at the
  631.      * end of each line to make it high enough.  I'm not using regular
  632.      * \strut commands, because my own TeX code is not careful about
  633.      * keeping \strut defined appropriately for the font in use.
  634.      */
  635.     printf ("\n\n{\\parskip=0pt\\offinterlineskip%%\n");
  636.  
  637.     while (1) {
  638.     if (!tree) {
  639.         printf ("\\vrule width0em height%1.3fex depth%1.3fex",h,d);
  640.         printf ("\\par}\n");
  641.         bufp = buf; /* can reuse string buffer for next tree */
  642.         /* (could free malloc'd memory for tree nodes, too) */
  643.         return;
  644.     }
  645.     if (tree->row > row) {
  646.         /* Put a strut at the end of each line.  The height and
  647.          * depth were determined by set_hd, called by boxitup.
  648.          */
  649.         printf ("\\vrule width0em height%1.3fex depth%1.3fex",h,d);
  650.         /* prevent page breaks in midst of tree */
  651.         printf ("\\par\\penalty10000\n");
  652.         row++;
  653.         col = 0;
  654.         hskip = (float) indent / 2;
  655.     }
  656.     else if ((tree->row == row)
  657.           && (tree->col == col)) {
  658.         boxitup(tree);
  659.         col += tree->l;
  660.         tree = tree->right;
  661.     }
  662.     else {
  663.         /* to advance one column, hskip 1/4 em, which is only 1/2
  664.          * en space, since we doubled all the col values
  665.          */
  666.         hskip +=.50/COLMUL;
  667.         col++;
  668.     }
  669.     }
  670. }
  671.